// SPI Master Controller
// FPGA Clock: 27MHz
module spi_master (
    input wire       clk,      // 27MHz clock
    input wire       rst_n,    // Active low reset
    input wire [7:0] data_in,  // Data to be transmitted
    input wire       start,    // Start signal

    output reg        sclk,     // SPI clock
    output reg        mosi,     // Master Out Slave In
    input  wire       miso,     // Master In Slave Out
    output reg        cs_n,     // Chip Select (Active Low)
    output reg        busy,     // Busy flag
    output reg  [7:0] data_out  // Received data
);

  // Parameters
  localparam integer IDLE = 2'b00, TRANSFER = 2'b01, DONE = 2'b10;
  localparam integer SCLK_DIV = 4;  // SPI clock divider (27MHz / 4 = 6.75MHz)
  parameter integer CPOL = 0, CPHA = 0;  // Clock polarity and phase

  // Registers
  reg [1:0] state, next_state;
  reg [7:0] shift_reg;
  reg [3:0] bit_cnt;
  reg [2:0] clk_div_cnt;

  // State Machine
  always @(posedge clk or negedge rst_n) begin
    if (!rst_n) state <= IDLE;
    else state <= next_state;
  end

  always_comb begin
    case (state)
      IDLE:
      if (start) next_state = TRANSFER;
      else next_state = IDLE;
      TRANSFER:
      if (bit_cnt == 4'd8 && clk_div_cnt == SCLK_DIV - 1) next_state = DONE;
      else next_state = TRANSFER;
      DONE: next_state = IDLE;
      default: next_state = IDLE;
    endcase
  end

  // SPI Clock Generation
  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      sclk <= CPOL;
      clk_div_cnt <= 0;
    end else if (state == TRANSFER) begin
      if (clk_div_cnt == SCLK_DIV / 2 - 1) begin
        sclk <= ~CPOL;
        clk_div_cnt <= clk_div_cnt + 1;
      end else if (clk_div_cnt == SCLK_DIV - 1) begin
        sclk <= CPOL;
        clk_div_cnt <= 0;
      end else begin
        clk_div_cnt <= clk_div_cnt + 1;
      end
    end else begin
      sclk <= CPOL;
      clk_div_cnt <= 0;
    end
  end

  // Data Transmission and Reception
  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      shift_reg <= 8'b0;
      bit_cnt <= 0;
      mosi <= 0;
      data_out <= 8'b0;
    end else if (state == IDLE) begin
      shift_reg <= data_in;
      bit_cnt   <= 0;
    end else if (state == TRANSFER &&
                ((CPHA == 1 && clk_div_cnt == SCLK_DIV - 2)
                || (CPHA == 0 && clk_div_cnt == SCLK_DIV / 2 - 2))) begin
      mosi <= shift_reg[7];
      shift_reg <= {shift_reg[6:0], miso};
      if (bit_cnt < 4'd8) bit_cnt <= bit_cnt + 1;
    end else if (state == DONE) begin
      data_out <= shift_reg;
      bit_cnt  <= 0;
    end
  end

  // Chip Select and Busy Flag
  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      cs_n <= 1;
      busy <= 0;
    end else begin
      case (state)
        IDLE: begin
          cs_n <= 1;
          busy <= 0;
        end
        TRANSFER: begin
          cs_n <= 0;
          busy <= 1;
        end
        DONE: begin
          cs_n <= 1;
          busy <= 0;
        end
        default: begin
          cs_n <= 1;
          busy <= 0;
        end
      endcase
    end
  end

endmodule
